package com.trayicon.messagenotifier.main;

import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import com.trayicon.messagenotifier.http.HttpClientUtility;

public class CustomDictionary {
	private static CustomDictionary THIS = null;
	private List<Word> resources = new ArrayList<Word>(50);
	
	private DicInfo usingDic = null;
	
	/**
	 * Default constructor
	 */
	private CustomDictionary() {
		usingDic = new DicInfo();
		loadDic();
	}
	
	public static CustomDictionary GET() {
		if (THIS == null) {
			THIS = new CustomDictionary();
		}
		return THIS;
	}
	
	private JSONParser parser = new JSONParser();
	
	private void loadDefaultRemoteDic() {
		List<Word> lstDefault = HttpClientUtility.getInstance().getDefaultBook();
		if (lstDefault != null && !lstDefault.isEmpty()) {
			resources.addAll(lstDefault);
		}
	}
	private void loadDic() {
		// try to load remote dic
		loadDefaultRemoteDic();
		if (resources.size() > 0) {
			usingDic.setLocalDic(false);
			usingDic.setName("get_default_book");
			
			return;
		}
		
		usingDic.setLocalDic(true);
		usingDic.setName("TBD");
		// load local dic
		try {
			File dicDir = new File(Constant.DIC_DIR);
			Reader fr = null;
			List<JSONObject> lstJsonObject = new ArrayList<JSONObject>(5);
			
			if (dicDir.isDirectory()) {
				File[] files = dicDir.listFiles(new FileFilter() {
					
					@Override
					public boolean accept(File arg0) {
						if (arg0.getName().endsWith(".json")) {
							return true;
						}
						return false;
					}
				});
				
				if (files.length > 0) {
					for (File f : files) {
						fr = new FileReader(f);
						JSONObject jsonObject = (JSONObject) parser.parse(fr);
						if (jsonObject != null) {
							lstJsonObject.add(jsonObject);
						}
						
						if (fr != null) {
							try {
								fr.close();
							} catch (Exception e) {}
						}
					}
				}
			}

			if (lstJsonObject.size() == 0) {
				// load default dictionary
				InputStream is = CustomDictionary.class.getResourceAsStream("/data.json");
				fr = new InputStreamReader(is);
				JSONObject jsonObject = (JSONObject) parser.parse(fr);
				lstJsonObject.add(jsonObject);
				if (fr != null) {
					try {
						fr.close();
					} catch (Exception e) {}
				}
			}
	 
			// loop array
			for (JSONObject jobj : lstJsonObject) {
				JSONArray msg = (JSONArray) jobj.get("dic");
				@SuppressWarnings("unchecked")
				Iterator<JSONObject> iterator = msg.iterator();
				JSONObject json;
				while (iterator.hasNext()) {
					json = iterator.next();
					Word w = new Word(json.get("word").toString(), json.get("meaning").toString());
					w.setImagePath(json.get("imagePath").toString());
					resources.add(w);
				}
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		}
		
		if (Constant.DEBUG_DICTIONARY) {
			System.out.println("========== Finished loading Dictionary ==========");
			for (Word w : resources) {
				System.out.println("- " +w.getWord()+ "; " +w.getMeaning() + "; " +w.getImagePath());
			}
		}
	}
	
	@SuppressWarnings({ "unchecked", "unused" })
	private void insertDefaultDic() {
		JSONObject obj = new JSONObject();
	 
		JSONArray list = new JSONArray();
		JSONObject json = new JSONObject();
		json.put("word", "hello");
		json.put("meaning", "");
		json.put("imagePath", "");
		list.add(json);
		obj.put("dic", list);
		FileWriter fw = null;
		try {
			fw = new FileWriter("data.json");
			fw.write(obj.toJSONString());
			fw.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (fw != null) {
				try {
					fw.close();
				} catch (Exception e) {
				}
			}
		}
	}
	
	@SuppressWarnings("unchecked")
	private void saveDic() {
		JSONObject obj = new JSONObject();
		JSONArray list = new JSONArray();
		
		for (Word w : resources) {
			JSONObject json = new JSONObject();
			json.put("word", w.getWord());
			json.put("meaning", w.getMeaning());
			json.put("imagePath", w.getImagePath());
			list.add(json);
		}
		obj.put("dic", list);
		FileWriter file = null;
		try {
			file = new FileWriter(Constant.DIC_DIR + "data.json");
			file.write(obj.toJSONString());
			file.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (file != null) {
				try {
					file.close();
				} catch(Exception ex) {}
			}
		}
	}
	
	public void addWord(Word word) {
		if (word != null) {
			resources.add(word);
			HttpClientUtility.getInstance().addWord(word);
		}
		
		saveDic();
	}
	
	public void removeWord(Word word) {
		if (resources.contains(word)) {
			resources.remove(word);
		}
	}
	
	private static int index = 0;
	public Word getNextWord() {
		if (index == resources.size()) {
			index = 0;
		}
		Word w = resources.get(index);
		index++;
		
		return w;
	}
	
	public Word getRandomWord() {
		Random r = new Random();
		int index = r.nextInt(resources.size());
		
		return resources.get(index);
	}
	
	public void deleteWord(String word) {
		if (resources.size() < 1) {
			// ohm no, its the last one, please, don't
			System.out.println("Hey man, this is the last word," +
			" I will not delete this one, hahaha");
			return;
		}
		for (int i = 0; i < resources.size(); i++) {
			Word w = resources.get(i);
			if (w.getWord().equalsIgnoreCase(word)) {
				resources.remove(i);
				saveDic();
				return;
			}
		}
	}

}
